package com.sc.nft.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.lang.Assert;
import com.sc.nft.dao.DaoChainInfoDao;
import com.sc.nft.dao.UserChainInfoDao;
import com.sc.nft.dao.UserCollectionChainLogDao;
import com.sc.nft.entity.*;
import com.sc.nft.enums.*;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.service.DaoService;
import com.sc.nft.service.PrivilegeService;
import com.sc.nft.sup.ErrorCode;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import com.sc.nft.service.DaoChainInfoService;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * Dao上链信息服务接口实现
 *
 * @author zxy
 * @since 2023-05-17 14:20:36
 * @description 活动推荐表
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class DaoChainInfoServiceImpl implements DaoChainInfoService {
    private final DaoChainInfoDao daoChainInfoDao;
    private final PrivilegeService privilegeService;
    private final DaoService daoService;
    private final UserChainInfoDao userChainInfoDao;
    private final UserCollectionChainLogDao userCollectionChainLogDao;

    @Override
    public void transactionNft(MallOrder mallOrder, List<UserCollection> userCollectionList, MallOrderProduct mallOrderProduct) {
        for (UserCollection userCollection : userCollectionList) {
            //处理用户藏品
            userCollection.setGiveStatus(GiveStatusEnum.GIVE_OVER);
            userCollection.setGiveTime(DateTime.now());
            userCollection.setGiveSuccessTime(DateTime.now());
            userCollection.setIsHold(Boolean.FALSE);
            userCollection.setToUserId(mallOrder.getDaoId());

            if (!userCollection.updateById()) {
                throw new GlobalRunTimeException(ErrorCode.THE_SYSTEM_IS_BUSY_PLEASE_TRY_AGAIN_LATER);
            }

            //刷新用户等级
            privilegeService.flushUserLevel(userCollection.getUserId());
            //降级逻辑
            daoService.downgrade(userCollection.getCollectionId(), userCollection.getUserId(), ReceivedCollectionType.GIVE);

            //添加订单记录
            MallOrderExchange nftOrder = new MallOrderExchange();
            nftOrder.setOrderId(mallOrder.getId());
            nftOrder.setOrderProductId(mallOrderProduct.getId());
            nftOrder.setActivityId(mallOrderProduct.getActivityId());
            nftOrder.setActivitySpecsId(mallOrderProduct.getActivitySpecsId());
            nftOrder.setLinkName(userCollection.getFirstTitle());
            nftOrder.setLinkId(userCollection.getId());
            nftOrder.setType(MallExchangeEnum.NFT);
            nftOrder.setCostNum(1);
            nftOrder.insert();


            DaoChainInfo daoChainInfo = daoChainInfoDao.getByDaoId(mallOrder.getDaoId());
            UserCollectionChainLog userCollectionChain = userCollectionChainLogDao.getOneByUserIdAndUserCollectionId(userCollection.getUserId(), userCollection.getId());
            UserChainInfo fromUser = userChainInfoDao.getByUserId(mallOrder.getUserId());

            Assert.notNull(daoChainInfo,() -> new GlobalRunTimeException(ErrorCode.THE_MERCHANT_IS_NOT_ON_THE_CHAIN));
            Assert.notNull(fromUser,() -> new GlobalRunTimeException(ErrorCode.THE_COLLECTION_CONSUMED_BY_THE_EXCHANGE_IS_BEING_TRADED_ON_THE_CHAIN));
            Assert.notNull(userCollectionChain,() -> new GlobalRunTimeException(ErrorCode.THE_TRANSACTION_ON_THE_COLLECTION_CHAIN_CONSUMED_BY_THE_EXCHANGE_FAILED));

            //DAO仓库信息
            DaoCollectionStore daoCollectionStore = new DaoCollectionStore();
            daoCollectionStore.setDaoId(daoChainInfo.getDaoId());
            daoCollectionStore.setToUserId(0L);
            daoCollectionStore.setCollectionId(userCollection.getCollectionId());
            daoCollectionStore.setOrderId(mallOrder.getId());
            daoCollectionStore.setNumbering(userCollection.getNumbering());
            daoCollectionStore.setStatus(ChainStatusEnum.NONE);
            daoCollectionStore.setFirstTitle(userCollection.getFirstTitle());
            daoCollectionStore.setCollectionImage(userCollection.getCollectionImage());
            daoCollectionStore.setCollectionUuid(userCollection.getCollectionUuid());
            daoCollectionStore.setIsHold(Boolean.TRUE);
            daoCollectionStore.setFromUserCollectionId(userCollection.getId());
            daoCollectionStore.setFromUserAddress(fromUser.getAddress());
            daoCollectionStore.setTokenId(userCollectionChain.getTokenId());
            daoCollectionStore.insert();


            //链执行表
            UserCollectionChainLog userCollectionChainLog = new UserCollectionChainLog();
            userCollectionChainLog.setUserId(0L);
            userCollectionChainLog.setDaoId(daoChainInfo.getDaoId());
            userCollectionChainLog.setUserCollectionId(daoCollectionStore.getId());
            userCollectionChainLog.setCollectionType(ReceivedCollectionType.RECEIVED);
            userCollectionChainLog.setType(UserChainTypeEnum.TRANSFER);
            userCollectionChainLog.setStatus(UserChainLogStatusEnum.WAIT);
            userCollectionChainLog.setCollectionId(userCollection.getCollectionId());
            userCollectionChainLog.setContractAddress(userCollectionChain.getContractAddress());
            userCollectionChainLog.setDeployTransactionHash(userCollectionChain.getDeployTransactionHash());
            userCollectionChainLog.setTokenId(userCollectionChain.getTokenId());
            userCollectionChainLog.setProductId(userCollection.getCollectionUuid());
            userCollectionChainLog.setAddress(daoChainInfo.getAddress());
            userCollectionChainLog.setFromUserId(userCollection.getUserId());
            userCollectionChainLog.setFromUserCollectionId(userCollection.getId());
            userCollectionChainLog.setFromUserAddress(fromUser.getAddress());
            userCollectionChainLog.setToUserId(daoChainInfo.getDaoId());
            //dao仓库id
            userCollectionChainLog.setToUserCollectionId(daoCollectionStore.getId());
            userCollectionChainLog.setToUserAddress(daoChainInfo.getAddress());
            userCollectionChainLog.setCollectionChainId(0L);
            userCollectionChainLog.insert();
        }
    }
}